// 包含项目头文件和系统头文件
#include "common.h"         // 包含项目公共定义
#include <pthread.h>        // 包含POSIX线程相关定义
#include <stdio.h>          // 包含标准输入输出函数
#include <stdlib.h>         // 包含标准库函数
#include <string.h>         // 包含字符串处理函数
#include <unistd.h>         // 包含标准符号常量和类型
#include <sys/stat.h>       // 包含数据返回结构体
#include <errno.h>          // 包含错误号定义
#include <fcntl.h>          // 包含文件控制选项
#include <dirent.h>         // 包含目录操作函数

// 定义全局任务链表头指针和互斥锁
TaskNode* task_list_head = NULL;                                    // 任务链表头节点初始化为空
pthread_mutex_t task_list_mutex = PTHREAD_MUTEX_INITIALIZER;        // 初始化互斥锁

/**
 * 将任务添加到链表中（线程安全）
 * @param task 指向要添加的任务的指针
 */
void add_task_to_list(Task* task) {
    pthread_mutex_lock(&task_list_mutex);                           // 加锁保护共享资源
    
    TaskNode* new_node = malloc(sizeof(TaskNode));                  // 为新节点分配内存
    if (new_node == NULL) {                                         // 检查内存分配是否成功
        pthread_mutex_unlock(&task_list_mutex);                     // 解锁
        return;                                                     // 分配失败则返回
    }
    
    new_node->task = *task;                                         // 复制任务数据到新节点
    new_node->next = task_list_head;                                // 新节点指向原头节点
    task_list_head = new_node;                                      // 更新头节点为新节点
    
    pthread_mutex_unlock(&task_list_mutex);                         // 解锁
}

/**
 * 释放整个任务链表内存（线程安全）
 */
void free_task_list() {
    pthread_mutex_lock(&task_list_mutex);                           // 加锁保护共享资源
    
    TaskNode* current = task_list_head;                             // 从头节点开始遍历
    while (current != NULL) {                                       // 当节点不为空时循环
        TaskNode* next = current->next;                             // 保存下一个节点
        free(current);                                              // 释放当前节点内存
        current = next;                                             // 移动到下一个节点
    }
    
    task_list_head = NULL;                                          // 将头节点置为空
    pthread_mutex_unlock(&task_list_mutex);                         // 解锁
}

/**
 * 任务处理线程函数
 * 为每个任务创建一个线程来处理，根据任务类型执行相应操作
 * @param arg 指向任务数据的指针
 * @return NULL
 */
void* task_worker(void* arg) {
    Task* task = (Task*)arg;                                        // 将参数转换为任务指针
    
    // 更新任务状态为运行中，并记录开始时间
    task->status = TASK_RUNNING;                                    // 设置任务状态为运行中
    task->start_time = time(NULL);                                  // 记录任务开始时间
    
    // 根据任务类型处理不同任务
    switch (task->type) {                                           // 根据任务类型分支处理
        case TASK_FILE_TRANSFER:                                    // 处理文件传输任务
            // 文件保存逻辑
            {
                // 解析输入数据，格式为"filename|content"
                char* delimiter = strchr(task->data, '|');          // 查找分隔符'|'
                if (delimiter != NULL) {                            // 如果找到分隔符
                    *delimiter = '\0';                              // 将分隔符替换为字符串结束符
                    char* filename = task->data;                    // 分隔符前的部分为文件名
                    char* content = delimiter + 1;                  // 分隔符后的部分为文件内容
                    
                    // 创建文件并写入内容
                    FILE* file = fopen(filename, "w");              // 以写入模式打开文件
                    if (file != NULL) {                             // 如果文件打开成功
                        fputs(content, file);                       // 将内容写入文件
                        fclose(file);                               // 关闭文件
                        snprintf(task->result, sizeof(task->result), "文件已保存: %s", filename);  // 设置成功结果
                    } else {                                        // 如果文件打开失败
                        snprintf(task->result, sizeof(task->result), "错误: 无法创建文件 %s", filename);  // 设置错误结果
                    }
                } else {                                            // 如果未找到分隔符
                    // 如果没有分隔符，将整个数据作为文件名，创建空文件
                    FILE* file = fopen(task->data, "w");            // 以写入模式打开文件
                    if (file != NULL) {                             // 如果文件打开成功
                        fclose(file);                               // 关闭文件（创建空文件）
                        snprintf(task->result, sizeof(task->result), "空文件已创建: %s", task->data);  // 设置成功结果
                    } else {                                        // 如果文件打开失败
                        snprintf(task->result, sizeof(task->result), "错误: 无法创建文件 %s", task->data);  // 设置错误结果
                    }
                }
            }
            break;                                                  // 跳出switch语句
            
        case TASK_STRING_STORE:                                     // 处理字符串存储任务
            // 字符串存储逻辑
            {
                // 将字符串存储到string_data.txt文件中
                FILE* file = fopen("string_data.txt", "a");         // 以追加模式打开文件
                if (file != NULL) {                                 // 如果文件打开成功
                    // 格式化时间
                    char time_str[64];                              // 定义时间字符串缓冲区
                    time_t now = task->start_time;                  // 获取任务开始时间
                    struct tm* local_time = localtime(&now);        // 转换为本地时间
                    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", local_time);  // 格式化时间为字符串
                    
                    fprintf(file, "[PID: %d, Time: %s] %s\n", task->sender_pid, time_str, task->data);  // 写入带PID和时间的数据
                    fclose(file);                                   // 关闭文件
                    snprintf(task->result, sizeof(task->result), 
                            "字符串已存储至string_data.txt，PID %d，时间 %s", 
                            task->sender_pid, time_str);            // 设置成功结果
                } else {                                            // 如果文件打开失败
                    snprintf(task->result, sizeof(task->result), "错误: 无法打开string_data.txt文件");  // 设置错误结果
                }
            }
            break;                                                  // 跳出switch语句
            
        case TASK_QUERY_FILES:                                      // 处理文件查询任务
            // 文件查询逻辑 - 查询由系统操作过的文件
            {
                char buffer[2048] = {0};                            // 定义结果缓冲区并初始化为0
                int len = 0;                                        // 定义已使用缓冲区长度
                
                len += snprintf(buffer + len, sizeof(buffer) - len, "操作过的文件列表: ");  // 添加标题到缓冲区
                
                pthread_mutex_lock(&task_list_mutex);               // 加锁保护任务链表
                TaskNode* current = task_list_head;                 // 从任务链表头开始遍历
                int count = 0;                                      // 初始化文件计数器
                char file_names[100][256];                          // 定义文件名存储数组
                int file_count = 0;                                 // 初始化文件名计数器
                
                // 遍历任务链表，找出文件传输任务
                while (current != NULL && count < 20) {             // 当节点不为空且文件数小于20时循环
                    if (current->task.type == TASK_FILE_TRANSFER) { // 如果是文件传输任务
                        // 解析文件名（从data字段中提取）
                        char filename[256];                         // 定义文件名缓冲区
                        strncpy(filename, current->task.data, sizeof(filename) - 1);  // 复制任务数据到文件名缓冲区
                        filename[sizeof(filename) - 1] = '\0';      // 确保字符串结束符
                        
                        // 查找分隔符'|'
                        char* delimiter = strchr(filename, '|');    // 查找分隔符
                        if (delimiter != NULL) {                    // 如果找到分隔符
                            *delimiter = '\0';                      // 截断为纯文件名
                        }
                        
                        // 检查是否已存在
                        int found = 0;                              // 初始化查找标志
                        for (int i = 0; i < file_count; i++) {      // 遍历已存储的文件名
                            if (strcmp(file_names[i], filename) == 0) {  // 如果文件名已存在
                                found = 1;                          // 设置查找标志
                                break;                              // 跳出循环
                            }
                        }
                        
                        // 如果未找到，则添加
                        if (!found && file_count < 100) {           // 如果文件名不存在且未超出限制
                            strncpy(file_names[file_count], filename, sizeof(file_names[file_count]) - 1);  // 存储文件名
                            file_names[file_count][sizeof(file_names[file_count]) - 1] = '\0';  // 确保字符串结束符
                            file_count++;                           // 增加文件名计数器
                            
                            if (count > 0) {                        // 如果不是第一个文件
                                len += snprintf(buffer + len, sizeof(buffer) - len, ", ");  // 添加分隔符
                            }
                            len += snprintf(buffer + len, sizeof(buffer) - len, "%s", filename);  // 添加文件名
                            count++;                                // 增加文件计数器
                        }
                    }
                    current = current->next;                        // 移动到下一个节点
                }
                pthread_mutex_unlock(&task_list_mutex);             // 解锁任务链表
                
                if (count == 0) {                                   // 如果没有找到文件
                    len += snprintf(buffer + len, sizeof(buffer) - len, "无");  // 添加"无"到结果
                }
                
                strncpy(task->result, buffer, sizeof(task->result) - 1);  // 复制结果到任务结果字段
                task->result[sizeof(task->result) - 1] = '\0';      // 确保字符串结束符
            }
            break;                                                  // 跳出switch语句
            
        case TASK_QUERY_TASKS:                                      // 处理任务查询任务
            // 任务查询逻辑
            {
                pthread_mutex_lock(&task_list_mutex);               // 加锁保护任务链表
                char buffer[2048] = {0};                            // 定义结果缓冲区并初始化为0
                int len = 0;                                        // 定义已使用缓冲区长度
                
                len += snprintf(buffer + len, sizeof(buffer) - len, "任务列表:\n");  // 添加标题到缓冲区
                
                TaskNode* current = task_list_head;                 // 从任务链表头开始遍历
                int count = 0;                                      // 初始化任务计数器
                while (current != NULL && len < sizeof(buffer) - 256) {  // 当节点不为空且缓冲区未满时循环
                    char* status_str;                               // 定义状态字符串指针
                    switch (current->task.status) {                 // 根据任务状态分支
                        case TASK_PENDING: status_str = "待处理"; break;  // 待处理状态
                        case TASK_RUNNING: status_str = "运行中"; break;  // 运行中状态
                        case TASK_COMPLETED: status_str = "已完成"; break;  // 已完成状态
                        default: status_str = "未知"; break;        // 未知状态
                    }
                    
                    char* type_str;                                 // 定义类型字符串指针
                    switch (current->task.type) {                   // 根据任务类型分支
                        case TASK_FILE_TRANSFER: type_str = "文件传输"; break;  // 文件传输类型
                        case TASK_STRING_STORE: type_str = "字符串存储"; break;  // 字符串存储类型
                        case TASK_QUERY_FILES: type_str = "查询文件"; break;  // 查询文件类型
                        case TASK_QUERY_TASKS: type_str = "查询任务"; break;  // 查询任务类型
                        case TASK_COMPUTE: type_str = "计算"; break;  // 计算类型
                        default: type_str = "未知"; break;          // 未知类型
                    }
                    
                    len += snprintf(buffer + len, sizeof(buffer) - len, 
                            "任务 %d [PID: %d, 类型: %s, 状态: %s]\n", 
                            ++count, current->task.sender_pid, type_str, status_str);  // 添加任务信息到缓冲区
                    current = current->next;                        // 移动到下一个节点
                }
                
                if (count == 0) {                                   // 如果没有任务
                    len += snprintf(buffer + len, sizeof(buffer) - len, "暂无任务");  // 添加"暂无任务"到缓冲区
                }
                
                pthread_mutex_unlock(&task_list_mutex);             // 解锁任务链表
                strncpy(task->result, buffer, sizeof(task->result) - 1);  // 复制结果到任务结果字段
                task->result[sizeof(task->result) - 1] = '\0';      // 确保字符串结束符
            }
            break;                                                  // 跳出switch语句
            
        case TASK_COMPUTE:                                          // 处理计算任务
            // 计算任务逻辑
            {
                int a, b;                                           // 定义两个操作数
                char op;                                            // 定义操作符
                int result;                                         // 定义计算结果
                int parsed = sscanf(task->data, "%d %c %d", &a, &op, &b);  // 解析表达式
                if (parsed != 3) {                                  // 如果解析失败
                    snprintf(task->result, sizeof(task->result), "错误: 表达式格式错误 '%s'", task->data);  // 设置错误结果
                    break;                                          // 跳出switch语句
                }
                
                switch(op) {                                        // 根据操作符分支处理
                    case '+':                                       // 加法运算
                        result = a + b;                             // 执行加法运算
                        snprintf(task->result, sizeof(task->result), "%d + %d = %d", a, b, result);  // 设置结果
                        break;                                      // 跳出switch语句
                    case '-':                                       // 减法运算
                        result = a - b;                             // 执行减法运算
                        snprintf(task->result, sizeof(task->result), "%d - %d = %d", a, b, result);  // 设置结果
                        break;                                      // 跳出switch语句
                    case '*':                                       // 乘法运算
                        result = a * b;                             // 执行乘法运算
                        snprintf(task->result, sizeof(task->result), "%d * %d = %d", a, b, result);  // 设置结果
                        break;                                      // 跳出switch语句
                    case '/':                                       // 除法运算
                        if (b != 0) {                               // 如果除数不为0
                            result = a / b;                         // 执行除法运算
                            snprintf(task->result, sizeof(task->result), "%d / %d = %d", a, b, result);  // 设置结果
                        } else {                                    // 如果除数为0
                            snprintf(task->result, sizeof(task->result), "错误: 除零错误");  // 设置错误结果
                        }
                        break;                                      // 跳出switch语句
                    default:                                        // 不支持的操作符
                        snprintf(task->result, sizeof(task->result), "错误: 不支持的操作符 '%c'", op);  // 设置错误结果
                        break;                                      // 跳出switch语句
                }
            }
            break;                                                  // 跳出switch语句
            
        default:                                                    // 处理未知任务类型
            snprintf(task->result, sizeof(task->result), "错误: 未知任务类型 %d", task->type);  // 设置错误结果
            break;                                                  // 跳出switch语句
    }
    
    // 更新任务状态为已完成，记录结束时间和执行时间
    task->status = TASK_COMPLETED;                                  // 设置任务状态为已完成
    task->end_time = time(NULL);                                    // 记录任务结束时间
    task->exec_time = difftime(task->end_time, task->start_time);   // 计算任务执行时间
    
    // 添加任务到链表
    add_task_to_list(task);                                         // 将任务添加到链表中
    
    // 通过管道返回结果给客户端
    int pipe_fd = open(PIPE_PATH, O_WRONLY);                        // 以写入模式打开命名管道
    if (pipe_fd != -1) {                                            // 如果管道打开成功
        ssize_t written = write(pipe_fd, task, sizeof(Task));       // 向管道写入任务数据
        if (written == -1) {                                        // 如果写入失败
            perror("写入管道失败");                                 // 打印错误信息
        }
        close(pipe_fd);                                             // 关闭管道
    } else {                                                        // 如果管道打开失败
        perror("无法打开管道进行写入");                             // 打印错误信息
    }
    
    // 释放分配的内存
    free(task);                                                     // 释放任务内存
    return NULL;                                                    // 返回空指针
}

/**
 * 主函数
 * 初始化消息队列和命名管道，等待并处理客户端发送的任务
 * @return 程序退出状态码
 */
int main() {
    // 创建消息队列
    int msqid = msgget(MSG_QUEUE_KEY, IPC_CREAT | 0666);            // 创建或获取消息队列
    if (msqid == -1) {                                              // 如果创建失败
        perror("创建消息队列失败");                                 // 打印错误信息
        exit(EXIT_FAILURE);                                         // 退出程序
    }
    
    // 创建命名管道
    if (mkfifo(PIPE_PATH, 0666) == -1 && errno != EEXIST) {         // 创建命名管道，如果已存在则忽略错误
        perror("创建命名管道失败");                                 // 打印错误信息
        exit(EXIT_FAILURE);                                         // 退出程序
    }
    
    printf("服务器已启动。等待任务...\n");                         // 打印服务器启动信息
    
    while (1) {                                                     // 无限循环等待任务
        TaskMessage msg;                                            // 定义消息结构体
        // 接收任务消息
        ssize_t result = msgrcv(msqid, &msg, sizeof(Task), 1, 0);   // 从消息队列接收消息
        if (result > 0) {                                           // 如果接收成功
            // 创建线程处理任务
            pthread_t tid;                                          // 定义线程ID
            Task* task_copy = malloc(sizeof(Task));                 // 为任务副本分配内存
            if (task_copy == NULL) {                                // 如果内存分配失败
                perror("为任务分配内存失败");                       // 打印错误信息
                continue;                                           // 继续下一次循环
            }
            *task_copy = msg.task;                                  // 复制任务数据
            task_copy->status = TASK_PENDING;                       // 初始化任务状态为待处理
            
            if (pthread_create(&tid, NULL, task_worker, task_copy) != 0) {  // 创建线程处理任务
                perror("创建线程失败");                             // 如果创建失败，打印错误信息
                free(task_copy);                                    // 释放任务副本内存
                continue;                                           // 继续下一次循环
            }
            pthread_detach(tid);                                    // 分离线程，避免内存泄漏
        } else if (result == -1 && errno != EINTR) {                // 如果接收失败且不是中断信号
            perror("接收消息失败");                                 // 打印错误信息
        }
    }
    
    // 清理资源（实际上不会执行到这里）
    free_task_list();                                               // 释放任务链表内存
    msgctl(msqid, IPC_RMID, NULL);                                  // 删除消息队列
    unlink(PIPE_PATH);                                              // 删除命名管道
    return 0;                                                       // 返回程序退出状态码
}